package de.fhin.mas.ontology;

import jade.content.onto.BasicOntology;
import jade.content.onto.Ontology;
import jade.content.onto.OntologyException;
import jade.content.schema.ConceptSchema;
import jade.content.schema.ObjectSchema;
import jade.content.schema.PredicateSchema;
import jade.content.schema.PrimitiveSchema;

/**
 * Die Ontologie des fhin MAS. Enthält alle "Datenobjekte" die zwischen den
 * Agenten ausgetauscht werden müssen
 * 
 * @author Thomas Schlaefer
 */
public class MASOntology extends Ontology {
	/**
	 * 
	 */
	private static final long serialVersionUID = -1243255897712821150L;

	// NAME
	public static final String ONTOLOGY_NAME = "MAS-ontology";

	// Concepts:
	public static final String SEARCHABLE_OBJECT = "SearchableObject";
	public static final String SEARCHABLE_OBJECT_NAME = "name";
	public static final String SEARCHABLE_OBJECT_COLOR = "color";
	public static final String SEARCHABLE_OBJECT_SHAPE = "shape";
	public static final String SEARCHABLE_OBJECT_HEIGHT = "height";
	public static final String SEARCHABLE_OBJECT_WIDTH = "width";
	public static final String SEARCHABLE_OBJECT_DEPTH = "depth";

	public static final String LOCATION = "Location";
	public static final String LOCATION_DESCRIPTION = "description";
	public static final String LOCATION_X_COORDINATE = "x_coordinate";
	public static final String LOCATION_Y_COORDINATE = "y_coordinate";
	public static final String LOCATION_TYPE = "type";

	public static final String TARGET_SEARCH_RESULT = "TargetSearchResult";
	public static final String TARGET_SEARCH_RESULT_DATE = "date";
	public static final String TARGET_SEARCH_RESULT_ANGLE = "angle";
	public static final String TARGET_SEARCH_RESULT_DISTANCE = "distance";

	public static final String ENVIRONMENT_SCAN_RESULT = "EnvironmentScanResult";
	public static final String ENVIRONMENT_SCAN_RESULT_DATE = "date";
	public static final String ENVIRONMENT_SCAN_RESULT_OBSTACLES = "obstacles";

	public static final String RELATIVE_DISTANCE = "RelativeDistance";
	public static final String RELATIVE_DISTANCE_ANGLE = "angle";
	public static final String RELATIVE_DISTANCE_DISTANCE = "distance";

	// Predicates
	public static final String SEARCHABLE_OBJECT_DATA = "SearchableObjectData";
	public static final String SEARCHABLE_OBJECT_DATA_CONTENT = "searchObject";
	public static final String SEARCHABLE_OBJECT_DATA_LOCATION = "location";

	public static final String TARGET_DATA = "TargetData";
	public static final String TARGET_DATA_CONTENT = "target";

	public static final String LOCATION_DATA = "LocationData";
	public static final String LOCATION_DATA_CONTENT = "location";

	public static final String ENVIRONMENT_DATA = "EnvironmentData";
	public static final String ENVIRONMENT_DATA_CONTENT = "obstacles";

	// public static final String RELATIVE_DISTANCE_DATA =
	// "RelativeDistanceData";
	// public static final String RELATIVE_DISTANCE_DATA_CONTENT =
	// "RelativeDistance";

	// Singleton Instanz dieser Ontologie
	private static Ontology theInstance = new MASOntology();

	/**
	 * Über diese Methode kann man auf das Singleton Objekt MASOntology
	 * zugreifen
	 */
	public static Ontology getInstance() {
		return theInstance;
	}

	// Private constructor
	private MASOntology() {

		super(ONTOLOGY_NAME, BasicOntology.getInstance());
		try {

			// alle Concepts adden, quasi die "Dinge" mit denen wir in unserer
			// Welt hantieren.
			add(new ConceptSchema(SEARCHABLE_OBJECT), SearchableObject.class);
			add(new ConceptSchema(LOCATION), Location.class);
			add(new ConceptSchema(TARGET_SEARCH_RESULT), TargetSearchResult.class);
			add(new ConceptSchema(ENVIRONMENT_SCAN_RESULT), EnvironmentScanResult.class);
			add(new ConceptSchema(RELATIVE_DISTANCE), RelativeDistance.class);

			// alle Prädikate adden (die Container für die "Dinge")
			add(new PredicateSchema(SEARCHABLE_OBJECT_DATA), SearchableObjectData.class);
			add(new PredicateSchema(TARGET_DATA), TargetData.class);
			add(new PredicateSchema(LOCATION_DATA), LocationData.class);
			add(new PredicateSchema(ENVIRONMENT_DATA), EnvironmentData.class);
			// add(new PredicateSchema(RELATIVE_DISTANCE_DATA),
			// RelativeDistanceData.class);

			// Struktur des RelativeDistance Schemas:
			ConceptSchema cs = (ConceptSchema) getSchema(RELATIVE_DISTANCE);
			cs.add(RELATIVE_DISTANCE_ANGLE, (PrimitiveSchema) getSchema(BasicOntology.INTEGER), ObjectSchema.MANDATORY);
			cs.add(RELATIVE_DISTANCE_DISTANCE, (PrimitiveSchema) getSchema(BasicOntology.INTEGER),
					ObjectSchema.MANDATORY);

			// Struktur des SearchableObject Schemas festlegen:
			cs = (ConceptSchema) getSchema(SEARCHABLE_OBJECT);
			// Der Name ist ein String, und MUSS angegeben werden -> Mandatory
			cs.add(SEARCHABLE_OBJECT_NAME, (PrimitiveSchema) getSchema(BasicOntology.STRING), ObjectSchema.MANDATORY);
			/*
			 * TODO tsc: color und shape sind derzeit nur als Strings
			 * realisiert, sollten aber später mal komplexe Java Objekte sein
			 * (Color und Shape)
			 */
			cs.add(SEARCHABLE_OBJECT_COLOR, (PrimitiveSchema) getSchema(BasicOntology.STRING), ObjectSchema.MANDATORY);
			cs.add(SEARCHABLE_OBJECT_SHAPE, (PrimitiveSchema) getSchema(BasicOntology.STRING), ObjectSchema.MANDATORY);
			cs
					.add(SEARCHABLE_OBJECT_HEIGHT, (PrimitiveSchema) getSchema(BasicOntology.INTEGER),
							ObjectSchema.MANDATORY);
			cs.add(SEARCHABLE_OBJECT_WIDTH, (PrimitiveSchema) getSchema(BasicOntology.INTEGER), ObjectSchema.MANDATORY);
			cs.add(SEARCHABLE_OBJECT_DEPTH, (PrimitiveSchema) getSchema(BasicOntology.INTEGER), ObjectSchema.MANDATORY);

			// Struktur des Location Schemas:
			cs = (ConceptSchema) getSchema(LOCATION);
			cs.add(LOCATION_DESCRIPTION, (PrimitiveSchema) getSchema(BasicOntology.STRING), ObjectSchema.MANDATORY);
			cs.add(LOCATION_X_COORDINATE, (PrimitiveSchema) getSchema(BasicOntology.INTEGER), ObjectSchema.MANDATORY);
			cs.add(LOCATION_Y_COORDINATE, (PrimitiveSchema) getSchema(BasicOntology.INTEGER), ObjectSchema.MANDATORY);
			cs.add(LOCATION_TYPE, (PrimitiveSchema) getSchema(BasicOntology.INTEGER), ObjectSchema.MANDATORY);

			// Struktur des TargetSearchResult Schemas:
			cs = (ConceptSchema) getSchema(TARGET_SEARCH_RESULT);
			cs.add(TARGET_SEARCH_RESULT_DATE, (PrimitiveSchema) getSchema(BasicOntology.DATE), ObjectSchema.MANDATORY);
			cs.add(TARGET_SEARCH_RESULT_ANGLE, (PrimitiveSchema) getSchema(BasicOntology.INTEGER),
					ObjectSchema.MANDATORY);
			cs.add(TARGET_SEARCH_RESULT_DISTANCE, (PrimitiveSchema) getSchema(BasicOntology.INTEGER),
					ObjectSchema.MANDATORY);

			// Struktur des EnvironmentScanResult Schemas:
			cs = (ConceptSchema) getSchema(ENVIRONMENT_SCAN_RESULT);
			cs.add(ENVIRONMENT_SCAN_RESULT_DATE, (PrimitiveSchema) getSchema(BasicOntology.DATE),
					ObjectSchema.MANDATORY);
			// Das Umgebungssuchergebnis beinhaltet mehrere relative Koordinaten
			// zu den Hindernissen:
			cs.add(ENVIRONMENT_SCAN_RESULT_OBSTACLES, (ConceptSchema) getSchema(RELATIVE_DISTANCE), 1,
					ObjectSchema.UNLIMITED);

			// Struktur des SearchableObjectData Predicates
			PredicateSchema ps = (PredicateSchema) getSchema(SEARCHABLE_OBJECT_DATA);
			ps.add(SEARCHABLE_OBJECT_DATA_CONTENT, getSchema(SEARCHABLE_OBJECT));
			ps.add(SEARCHABLE_OBJECT_DATA_LOCATION, getSchema(LOCATION));

			// Struktur des TargetData Predicates
			ps = (PredicateSchema) getSchema(TARGET_DATA);
			ps.add(TARGET_DATA_CONTENT, getSchema(TARGET_SEARCH_RESULT));

			// Struktur des LocationData Predicates
			ps = (PredicateSchema) getSchema(LOCATION_DATA);
			ps.add(LOCATION_DATA_CONTENT, getSchema(LOCATION));

			// Struktur des EnvironmentData Predicates
			ps = (PredicateSchema) getSchema(ENVIRONMENT_DATA);
			ps.add(ENVIRONMENT_DATA_CONTENT, getSchema(ENVIRONMENT_SCAN_RESULT));

			// Struktur des RelativeDistanceData Predicates
			// ps = (PredicateSchema) getSchema(RELATIVE_DISTANCE_DATA);
			// ps.add(RELATIVE_DISTANCE_DATA_CONTENT,
			// getSchema(RELATIVE_DISTANCE));

		} catch (OntologyException oe) {
			oe.printStackTrace();
		}
	}
}